//
// Created by cube on 2020/8/23.
//

#ifndef COMPILERDOMEA1_SERVER_H
#define COMPILERDOMEA1_SERVER_H

#include <chrono>
#include <memory>

#include <atomic>
#include <mutex>

#include <map>
#include <set>

#include "AlgorihmTemplate.h"
#include "../Tools.h"
#include "../Container/ThreadContainer.h"

namespace Lib{

    template <typename R,typename ...T>
    class Service{
    public:
        virtual void init(T ...data){}
        virtual R work(T ...data){return R();}
        virtual void release(T ...data){}
    };

    class Server : public Service<void>{
    public:
        enum Status{
            Stop,
            Start
        };
    public:
        void setStatus(const Status& _status,bool block = false){
            __opt = _status;
            if(block){
                while(__status != __opt)
                    std::this_thread::yield();
            }
        }
        Status status() const {return __status;}
    protected:
        void run(){
            while (__opt != Status::Start)std::this_thread::yield();
            __status = Status::Start;
            __run_count++;
            if(__run_count == 1)init();
            while (__opt == Status::Start)work();
            __status = Status::Stop;
            __run_count--;
            if(__run_count == 0)release();
        }

        std::atomic<Status>         __opt;
        std::atomic<Status>         __status;
        std::atomic_int32_t         __run_count = 0;
    };

    //======================================================

    template <typename T>
    class Loop : public Lib::Server {
    public:
        void sendEvent(T event){if(!filter(event))__event_queue.lock()->push_back(event);}

        void exec(){setStatus(Status::Start);run();}
        void quit(bool block = false){setStatus(Status::Stop,block);}

    protected:
        void work() override {T event;while (__event_queue.getOne(event))action(event);}
        virtual bool filter(T& event){return false;}
        virtual void action(T& event){}

    protected:
        TContainer<T,std::deque<T>> __event_queue;
    };
}

#endif //COMPILERDOMEA1_SERVER_H
